﻿using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using Cvs.Compilers;
using CVS.DAL;
using Executors;
using Microsoft.CSharp;
using SubmissionsProcessingService.Utils;

namespace SubmissionsProcessingService
{
    class SubmissionsProcessor
    {
        private bool m_stopRequested;

        private readonly ICompiler m_compiler = new CSharpCompiler();

        private readonly SynchronizedHashtable m_processingSubmissionIds;

        public SubmissionsProcessor(SynchronizedHashtable processingSubmissionIds)
        {
            m_processingSubmissionIds = processingSubmissionIds;
        }

        public void ProcessSubmission()
        {
            while (!m_stopRequested)
            {
                try
                {
                    var submissions = DataRepository.GetPendingSubmissions();

                    foreach ( var submission in submissions )
                    {
                        if (submission == null || !this.m_processingSubmissionIds.Add(submission.Id))
                        {
                            WaitToTryAgain();
                            continue;
                        }
                        TryProcessPendingSubmission(submission);
                    }
                }
                catch (Exception e)
                {
                    // log exception
                    WaitToTryAgain();
                }
            }
        }

        private void TryProcessPendingSubmission(Submission submission)
        {
            try
            {
                ProcessPendingSubmission(submission);

                m_processingSubmissionIds.Remove(submission.Id);
            }
            catch (Exception)
            {
                m_processingSubmissionIds.Remove(submission.Id);

                throw;
            }
        }

        private void ProcessPendingSubmission(Submission submission)
        {
            var compilationResult = Compile( submission );

            PersistCompilationData( submission, compilationResult );

            if ( compilationResult.IsSuccessful )
            {
                var executor = new DotNetExecutor( );
                var outputs = executor.Execute(
                    new List< string >
                    {
                        "1,2,6",
                        "1,6,1,6,32,1,2",
                        "23,1,43,54,13,46,35,13,21"
                    },
                    compilationResult.OutputFile );
            }
            
        }

        private CompilationResult Compile( Submission submission )
        {
            var outFile = "" + submission.Id + submission.TaskId;

            return m_compiler.Compile(submission.SourceCode, outFile); 
        }

        public void Stop()
        {
            this.m_stopRequested = true;
        }

        private void WaitToTryAgain()
        {
            Thread.Sleep(1000);
        }
    }
}
